package trpc

import (
	"bytes"
	"encoding/binary"
	"github.com/apache/dubbo-go-hessian2"
	log "github.com/sirupsen/logrus"
	"net"
	"sync"
	utils "thomas-mesh/pkg"
)

var SendChan = make(chan RpcPacket, 1024)
var ReceiveChan = make(chan RpcPacket, 1024)
var mutex sync.Mutex

type Client struct {
	Conn net.Conn
}

func (c *Client) Send(request Request) {
	c.Connect(request.ContextPath)
	e := hessian.NewEncoder()
	error := e.Encode(request)
	if error != nil {
		log.Error(error)
	}
	bodyBytes := e.Buffer()
	length := len(bodyBytes)
	buffer := bytes.Buffer{}
	buffer.Write(utils.IntToBytes(uint32(length)))
	buffer.Write([]byte{1})
	buffer.Write(bodyBytes)
	c.Conn.Write(buffer.Bytes())
}

func (client *Client) Connect(addr string) {
	if client.Conn == nil {
		mutex.Lock()
		if client.Conn == nil {
			tcpAddr, err := net.ResolveTCPAddr("tcp4", addr)
			if err != nil {
				log.Println(err)
			}
			client.Conn, err = net.DialTCP("tcp4", nil, tcpAddr)
			if err == nil {
				go func() {
					handleTcpCon(client.Conn, ReceiveChan, 65536)
				}()
			} else {
				client.Conn = nil
			}
		}
		mutex.Unlock()
	}
}

func handleTcpCon(conn net.Conn, receive chan RpcPacket, bufferSize int32) {
	defer func() {
		if e := recover(); e != nil {
			log.Errorf("recover:%v", e)
		}
	}()
	var buffer = bytes.NewBuffer(make([]byte, 0, bufferSize)) //buffer用来缓存读取到的数据
	readBytes := make([]byte, bufferSize)                     //readBytes用来接收每次读取的数据，每次读取完成之后将readBytes添加到buffer中
	var packet = RpcPacket{}
	for {
		//首先读取数据
		readByteNum, err := conn.Read(readBytes)
		if err != nil {
			log.Error(err)
			//conn.Close()
			return
		}
		buffer.Write(readBytes[0:readByteNum]) //将读取到的数据放到buffer中
		// 然后处理数据
		for {
			// body数据
			if packet.BodyLength != 0 && packet.Body == nil {
				if buffer.Len() >= int(packet.BodyLength) {
					bodyBytes := make([]byte, packet.BodyLength)
					_, err := buffer.Read(bodyBytes[:packet.BodyLength])
					if err != nil {
						log.Println(err)
					}
					packet.Body = bodyBytes
					//log.Println("Conn receive remote address:", conn.RemoteAddr(), "local address:", conn.LocalAddr(), "packetId:", packet.PacketId)
					newPacket := packet
					receive <- newPacket
					packet = RpcPacket{}
					if buffer.Len() == 0 {
						buffer.Reset()
						break
					}
					// 读取的body长度不够
				} else {
					log.Info("bufferLen:", buffer.Len(), " < expect:", packet.BodyLength)
					break
				}
			}
			// header数据
			if packet.PacketId == 0 {
				if buffer.Len() >= 5 {
					header := buffer.Next(5)
					//bodyLenBytes := buffer.Next(4)
					//bodyLen := binary.BigEndian.Uint32(bodyLenBytes)
					// 第一次组装 header 及bodylength
					packet.BodyLength = binary.BigEndian.Uint32(header[0:4])
					packet.ReqType = header[4]
					//packet.PacketType = header[5]
					//packet.BodyLength = bodyLen
					//if receive == SendChan {
					//	SendMap[packet.PacketId] = conn
					//} else if receive == ReceiveChan {
					//	ReceiveMap[packet.PacketId] = conn
					//}
				} else {
					log.Println("header < 10, bufferLen:", buffer.Len())
					break
				}
			}
		}
	}
}

func handleSendAndReceive(client Client) {
	for {
		select {
		//// 发送逻辑
		//case p := <-SendChan:
		//	log.Infof("reqType:%v, packetId:%v, packType:%v , length:%v", p.ReqType, p.PacketId, p.PacketType, p.BodyLength)
		//	// 服务发现
		//	address := discovery.DiscoveryService("uc-connector")
		//	if address != "" && &address != nil {
		//		client.Write(address, p.Bytes())
		//	}
		//// 接收逻辑
		case p := <-ReceiveChan:
			log.Infof("reqType:%v, packetId:%v, packType:%v , length:%v", p.ReqType, p.PacketId, p.PacketType, p.BodyLength)
			//conn := SendMap[p.PacketId]
			// 避免空指针
			//if conn != nil {
			//	conn.Write(p.Bytes())
			//	SendMap[p.PacketId] = nil
			//} else {
			//	if PushConn != nil {
			//		log.Println("消息推送:packetId:", p.PacketId)
			//		PushConn.Write(p.Bytes())
			//	}
			//}
		}
	}
}
